﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace EasyNet.Componets.Core.Domain.IdGenerator.Base36Id
{
    public class Base36Converter
    {
        private string _charList = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ";

        private readonly BaseConverter _baseConverter;
        public Base36Converter()
        {
            _baseConverter = new BaseConverter();
        }

        /// <summary>
        /// The character set for encoding. Defaults to upper-case alphanumerics 0-9, A-Z.
        /// </summary>
        public string CharList { get { return _charList; } set { _charList = value; } }
        public string FromHex(string hex)
        {
            return _baseConverter.Convert(hex, 16, 36);
        }
        public string FromGuid(Guid guid)
        {
            return _baseConverter.Convert(guid.ToString("N"), 16, 36);
        }
        public string FromInt32(long int32)
        {
            return _baseConverter.Convert(int32.ToString(), 10, 36);
        }
        public string FromInt64(long int64)
        {
            return _baseConverter.Convert(int64.ToString(), 10, 36);
        }
        /// <summary>
        /// Encode the given number into a Base36 string
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public String Encode(long input)
        {
            if (input < 0) throw new ArgumentOutOfRangeException("input", input, "input cannot be negative");
            char[] clistarr = CharList.ToCharArray();
            var result = new Stack<char>();
            while (input != 0)
            {
                result.Push(clistarr[input % 36]);
                input /= 36;
            }
            return new string(result.ToArray());
        }

        /// <summary>
        /// Decode the Base36 Encoded string into a number
        /// </summary>
        /// <param name="input"></param>
        /// <returns></returns>
        public Int64 Decode(string input)
        {
            var reversed = input.ToUpper().Reverse();
            long result = 0;
            int pos = 0;
            foreach (char c in reversed)
            {
                result += CharList.IndexOf(c) * (long)Math.Pow(36, pos);
                pos++;
            }
            return result;
        }
    }
}
